﻿using DataChangeTools.WebApi.IRepository.IRepositorys;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Org.BouncyCastle.Utilities.Zlib;
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;


namespace DataChangeTools.WebApi.Repository.Repositorys
{
    public class FileRepository : IFileRepository
    {
        private readonly ILogger<FileRepository> _logger;
        #region Property

        //private readonly IWebHostEnvironment _webHostEnvironment;

        #endregion

        #region Constructor

        //public FileRepository(IWebHostEnvironment webHostEnvironment)
        //{
        //    //_webHostEnvironment = webHostEnvironment;
        //} 
        public FileRepository(ILogger<FileRepository> logger)
        {
            _logger = logger;
            //_webHostEnvironment = webHostEnvironment;
        }

        #endregion

        #region Upload File

        public string UploadFile(List<IFormFile> files, string subDirectory)
        {
            var zipName = $"archive-{DateTime.Now:yyyy_MM_dd-HH_mm_ss}.zip";
            subDirectory = subDirectory ?? string.Empty;
            //var target = Path.Combine(_webHostEnvironment.ContentRootPath, subDirectory);
            var target = subDirectory;

            Directory.CreateDirectory(target);

            files.ForEach(async file =>
            {
                if (file.Length <= 0) return;
                //var filePath = Path.Combine(target, file.FileName);
                var filePath = Path.Combine(target, zipName);

                try
                {
                    using (var stream = new FileStream(filePath, FileMode.Create))
                    {
                        await file.CopyToAsync(stream);
                    }

                }
                catch (Exception e)
                {
                    throw new Exception(JsonConvert.SerializeObject(e));
                }

                //await using var stream = new FileStream(filePath, FileMode.Create);
                //await file.CopyToAsync(stream);
            });
            return zipName;
        }
        public async Task<string> UploadFile2(List<IFormFile> files, string subDirectory)
        {
            var zipName = $"archive-{DateTime.Now:yyyy_MM_dd-HH_mm_ss}.zip";
            subDirectory = subDirectory ?? string.Empty;
            //var target = Path.Combine(_webHostEnvironment.ContentRootPath, subDirectory);
            var target = subDirectory;

            Directory.CreateDirectory(target);

            files.ForEach(async file =>
            {
                if (file.Length <= 0) return;
                //var filePath = Path.Combine(target, file.FileName);
                var filePath = Path.Combine(target, zipName);

                try
                {
                    //using (var stream = new FileStream(filePath, FileMode.Create))
                    //{
                    //    await file.CopyToAsync(stream);
                    //}
                    var inputStream = file.OpenReadStream();
                    byte[] byteArr = new byte[inputStream.Length];
                    Stream stream = inputStream;
                    stream.Read(byteArr, 0, byteArr.Length);
                    using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write))
                    {
                        fs.Write(byteArr, 0, byteArr.Length);
                    }


                }
                catch (Exception e)
                {
                    _logger.LogError(JsonConvert.SerializeObject(e));
                    throw;
                }

                //await using var stream = new FileStream(filePath, FileMode.Create);
                //await file.CopyToAsync(stream);
            });
            return zipName;
        }

        #endregion

        #region Download File

        public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)
        {
            var zipName = $"archive-{DateTime.Now:yyyy_MM_dd-HH_mm_ss}.zip";

            var files = Directory.GetFiles(Path.Combine(subDirectory)).ToList();

            using var memoryStream = new MemoryStream();
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                files.ForEach(file =>
                {
                    var theFile = archive.CreateEntry(Path.GetFileName(file));
                    using var binaryWriter = new BinaryWriter(theFile.Open());
                    binaryWriter.Write(File.ReadAllBytes(file));
                });
            }

            return ("application/zip", memoryStream.ToArray(), zipName);
        }

        #endregion

        #region Size Converter

        public string SizeConverter(long bytes)
        {
            var fileSize = new decimal(bytes);
            var kilobyte = new decimal(1024);
            var megabyte = new decimal(1024 * 1024);
            var gigabyte = new decimal(1024 * 1024 * 1024);

            return fileSize switch
            {
                _ when fileSize < kilobyte => "Less then 1KB",
                _ when fileSize < megabyte =>
                    $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB",
                _ when fileSize < gigabyte =>
                    $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB",
                _ when fileSize >= gigabyte =>
                    $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB",
                _ => "n/a"
            };
        }
        public static List<string> GetAllDirectories(string path, string searchPattern = "*", SearchOption searchOption = SearchOption.TopDirectoryOnly)
        {
            List<string> directories = new List<string>();

            try
            {
                // 验证路径是否存在  
                if (!Directory.Exists(path))
                {

                    throw new DirectoryNotFoundException($"The path '{path}' could not be found.");
                }

                // 获取目录信息  
                DirectoryInfo directoryInfo = new DirectoryInfo(path);

                // 遍历目录和子目录  
                GetDirectoriesRecursive(directoryInfo, directories, searchPattern, searchOption);
            }
            catch (Exception ex)
            {
                // 处理异常，例如记录到日志等  
                Console.WriteLine($"An error occurred: {ex.Message}");
            }

            return directories;
        }
        private static void GetDirectoriesRecursive(DirectoryInfo directoryInfo, List<string> directories, string searchPattern, SearchOption searchOption)
        {
            // 获取当前目录下的文件夹  
            DirectoryInfo[] subDirs = directoryInfo.GetDirectories(searchPattern, searchOption);

            foreach (DirectoryInfo dir in subDirs)
            {
                // 将文件夹路径添加到列表中  
                directories.Add(dir.Name);

                // 如果需要搜索子目录，则递归调用  
                if (searchOption == SearchOption.AllDirectories)
                {
                    GetDirectoriesRecursive(dir, directories, searchPattern, searchOption);
                }
            }
        }
        public int[] SplitVersionStringToNumbers(string versionString)
        {
            // 使用Split方法按"."分割字符串  
            string[] parts = versionString.Split('.');

            // 使用Array.ConvertAll将字符串数组转换为整数数组  
            // 假设所有的部分都是有效的数字，否则需要添加异常处理  
            int[] numbers = Array.ConvertAll(parts, s => int.Parse(s));

            // 返回整数数组  
            return numbers;
        }
        public string GetVersion(string path)
        {
            try
            {
                var listmsg = GetAllDirectories(path);
                if (listmsg != null && listmsg.Count > 0)
                {
                    var listVersons = listmsg.FindAll(s => s.Length > 3);
                    Dictionary<int, string> dict = new Dictionary<int, string>();
                    foreach (var verson in listVersons)
                    {
                        var arryint = SplitVersionStringToNumbers(verson);
                        if (arryint != null && arryint.Count() == 4)
                        {
                            var value = arryint[0] * 1000 + arryint[1] * 100 + arryint[2] * 10 + arryint[3];
                            if (!dict.ContainsKey(value))
                            {
                                dict.Add(value, verson);
                            }
                        }
                    }
                    if (dict == null || !dict.Any())
                    {
                        return ""; // 或者抛出一个异常，取决于你的需求  
                    }

                    // 使用LINQ的Aggregate方法找到最大的key  
                    var objdict = dict.Aggregate((kvp1, kvp2) => kvp1.Key > kvp2.Key ? kvp1 : kvp2);


                    return objdict.Value;
                }
            }
            catch (Exception ee)
            {

            }
            return "";
        }
        #endregion
    }
}
